package com.gungnir.trial.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.tyrfing.model.Pagination;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;

import java.io.IOException;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author hjwang
 */
public class CommonUtils {
    private static final ObjectMapper mapper = new ObjectMapper()
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .enable(SerializationFeature.INDENT_OUTPUT)
            .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    /**
     * list去重
     *
     * @param list 列表
     * @return 列表
     */
    public static <T> List<T> removeDuplicate(List<T> list) {
        List<T> listTemp = new ArrayList<>();
        for (T t : list) {
            if (!listTemp.contains(t)) {
                listTemp.add(t);
            }
        }
        return listTemp;
    }

    /**
     * 去除尾部字符
     *
     * @param msg     原字符串
     * @param trimMsg 需要去除的字符
     * @return 字符串
     */
    public static String trimEnd(String msg, String trimMsg) {
        if (StringUtils.isBlank(msg)) {
            return msg;
        } else {
            String endMsg = msg.substring(msg.length() - 1);
            if (endMsg.equals(trimMsg)) {
                return msg.substring(0, msg.length() - 1);
            } else {
                return msg;
            }
        }
    }

    /**
     * 获取间隔分钟数-毫秒级时间戳
     *
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @return 整数
     */
    public static Integer getMinutes(Long beginTime, Long endTime) {
        Date date1 = new Date(beginTime);
        Date date2 = new Date(endTime);
        // 获得两个时间的毫秒时间差异
        long diff = date2.getTime() - date1.getTime();
        long nm = 1000 * 60;
        return (int) (diff / nm);
    }

    /**
     * 获取间隔天数中文说明-毫秒级时间戳
     *
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @return 整数
     */
    public static Integer getDays(Long beginTime, Long endTime) {
        Date date1 = new Date(beginTime);
        Date date2 = new Date(endTime);
        // 获得两个时间的毫秒时间差异
        long diff = date2.getTime() - date1.getTime();
        long nm = 1000 * 60;
        int minutes = (int) (diff / nm);
        if (minutes <= 0) {
            return 0;
        } else if (minutes < 60) {
            return 1;
        } else if (minutes <= 1440) {
            return 1;
        } else {
            return (minutes / 1440) + 1;
        }
    }

    /**
     * 获取间隔天数中文说明-毫秒级时间戳
     *
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @return 字符串
     */
    public static String getDaysMsg(Long beginTime, Long endTime) {
        return getDays(beginTime, endTime) + "天";
    }

    /**
     * 将对象转换为JSON字符串
     *
     * @param value 对象
     * @return Json字符串
     */
    public static String objectToJson(Object value) {
        try {
            return mapper.writeValueAsString(value);
        } catch (Exception e) {
            //logger.error("ERROR:", e);
        }
        return null;
    }

    /**
     * Json格式的字符串向JavaBean List集合转换，传入空串将返回null
     *
     * @param str 内容
     * @param c   对象类型
     * @return Json字符串
     */
    public static <T> List<T> jsonToObjectList(String str, Class<T> c) throws IOException {
        if (StringUtils.isBlank(str)) {
            return new ArrayList<>();
        } else {
            CollectionType collectionType = mapper.getTypeFactory().constructCollectionType(List.class, c);
            return mapper.readValue(str, collectionType);
        }
    }

    /**
     * 将对象转换为对象
     *
     * @param value     对象
     * @param valueType 类型
     * @return Json字符串
     */
    public static <T> T objectToObject(Object value, Class<T> valueType) {
        try {
            return mapper.convertValue(value, valueType);
        } catch (Exception e) {
            //logger.error("ERROR:", e);
        }
        return null;
    }

    /**
     * 将JSON字符串转换为对象
     *
     * @param jsonStr   JSON字符串
     * @param valueType 对象类型
     * @return 对象
     */
    public static <T> T jsonToObject(String jsonStr, Class<T> valueType) {
        try {
            return mapper.readValue(jsonStr, valueType);
        } catch (Exception e) {
            //logger.error("ERROR:", e);
        }
        return null;
    }

    /**
     * 将指定对象转换为数据列表
     *
     * @param obj   Object对象
     * @param clazz 列表类型
     * @return 列表
     */
    public static <T> List<T> objToList(Object obj, Class<T> clazz) {
        List<T> result = new ArrayList<>();
        if (obj instanceof List<?>) {
            for (Object o :
                    (List<?>) obj) {
                result.add(clazz.cast(o));
            }
            return result;
        }
        return null;
    }

    /**
     * 将JSON字符串转换为HashMap<String, Object>
     *
     * @param jsonStr JSON字符串
     * @return 对象
     */
    public static HashMap<String, Object> jsonToHashMap(String jsonStr) {
        try {
            return mapper.readValue(jsonStr, HashMap.class);
        } catch (Exception e) {
            return new HashMap<>();
        }
    }

    /**
     * Json格式的字符串向List<HashMap<String, Object>>转换，传入空串将返回null
     *
     * @param str 内容
     * @return List<HashMap < String, Object>>
     */
    public static List<HashMap<String, Object>> jsonToHashMapList(String str) throws IOException {
        if (StringUtils.isBlank(str)) {
            return new ArrayList<>();
        } else {
            return mapper.readValue(str, mapper.getTypeFactory().constructCollectionType(List.class, HashMap.class));
        }
    }

    /**
     * 分页数据格式转换
     */
    public static <T extends Serializable, R extends Serializable> Pagination<R> convertPagination(Pagination<T> sourcePagination, Function<T, R> converter) {
        List<R> convertedData = sourcePagination.getData().stream()
                .map(converter)
                .collect(Collectors.toList());
        Pagination<R> retPage = new Pagination<>();
        retPage.setTotal(sourcePagination.getTotal());
        retPage.setPageNum(sourcePagination.getPageNum());
        retPage.setPageSize(sourcePagination.getPageSize());
        retPage.setData(convertedData);
        return retPage;
    }

    public static <T extends Serializable> Pagination<T> of(Page<T> from) {
        Pagination<T> pagination = new Pagination<>();
        pagination.setTotal(from.getTotalElements());
        pagination.setPageSize(from.getSize());
        pagination.setPageNum(from.getNumber());
        pagination.setData(from.getContent());
        return pagination;
    }

    public static String formatDouble(Double doubleValue) {
        if (doubleValue == null) {
            return null;
        }
        // 使用 DecimalFormat 格式化分数，保留两位小数，即使是0
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(doubleValue);
    }
}
